
#include "stm32f10x.h"
#include "stm32f10x_flash.h"
#include "Flash_STM32.h"

typedef enum {
	FAILED = 0, PASSED = !FAILED
} TestStatus;

#define StartAddr  		((u32)0x0801E000)//start of page 120
#define EndAddr    		((u32)0x0801FFFF)//end of page 127
#define IDdeviceAddr		((u32)0x0801E000)//start of page 120
#define CurrentRFIDAddr	IDdeviceAddr + 20// the 20th byte of page 120
//#define CurrentRFIDAddr		((u32)0x0801E400)//start of page 121
#define FLASH_PAGE_SIZE 1024

u32 Data;
//vu32 NbrOfPage = 0x00;
#define NbrOfPage ((EndAddr - StartAddr) / FLASH_PAGE_SIZE)
volatile FLASH_Status FLASHStatus;
volatile TestStatus MemoryProgramStatus;
ErrorStatus HSEStartUpStatus;

u32 write_flash(u32 Address_user, unsigned int Data);
int WriteCurrentRFID(u32 RFID[]);
void ReadCurrentRFID(u32* RFID);
int WriteIDdevice(uint32_t IDdevice[4]);
void ReadIDdevice(u32* IDdevice);
unsigned int read_flash(u32 Address);
int erase_flash();

/*******************************************************************************
 * Function Name  write_flash
 * Description    write data to flash at Address_user
 * Input
 * Output
 * Return         Next address (if write successfully) or current address
 *******************************************************************************/
u32 write_flash(u32 Address_user, unsigned int Data) {
#ifdef DEBUG
	debug();
#endif

	FLASHStatus = FLASH_COMPLETE;
	MemoryProgramStatus = PASSED;

	if ((Address_user < StartAddr) || (Address_user > (EndAddr - 4))) {
		return Address_user;
	}
	/* Define the number of page to be erased */
	//NbrOfPage = (EndAddr - StartAddr) / FLASH_PAGE_SIZE;

	/* Clear All pending flags */
	FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR
			| FLASH_FLAG_WRPRTERR);
	/* Unlock the Flash Program Erase controller */
	FLASH_Unlock();
	FLASHStatus = FLASH_ProgramWord(Address_user, Data);
	FLASH_Lock();
	if (FLASHStatus == FLASH_COMPLETE) {
		Address_user = Address_user + 4;
		return Address_user;
	} else {
		return Address_user;
	}
}

/**********************************************************************
 * Write current RFID into flash at CurrentRFIDAddr
 *
 **********************************************************************/
int WriteCurrentRFID(u32 RFID[])
{
	int loop;
	u32 addr = CurrentRFIDAddr;
	u32 newaddr = 0;
	for(loop = 0; loop < 4; loop++)
	{
		newaddr = write_flash(addr,RFID[loop]);
		if(newaddr == addr)
			return 0;
		addr = newaddr;
	}
	return 1;
}

/**********************************************************************
 * read current RFID form flash at CurrentRFIDAddr
 *
 **********************************************************************/
void ReadCurrentRFID(u32* RFID)
{
	int loop;
	u32 addr = CurrentRFIDAddr;
	for(loop = 0; loop < 4; loop++)
	{
		RFID[loop] = read_flash(addr);
		addr = addr + 4;
	}
}
/**********************************************************************
 * name: WriteIDdevice
 * write ID device into flash at IDdeviceAddr
 *
 **********************************************************************/
int WriteIDdevice(u32 IDdevice[]) {
	int loop;
	u32 addr = IDdeviceAddr;
	u32 newaddr = 0;
	for(loop = 0; loop < 4; loop++)
	{
		newaddr = write_flash(addr,IDdevice[loop]);
		if(newaddr == addr)
			return 0;
		addr = newaddr;
	}
	return 1;
}

/***********************************************************************
 * read ID device form flash at IDdeviceAddr
 *
 *
 ***********************************************************************/
void ReadIDdevice(u32* IDdevice)
{
	int loop;
	u32 addr = IDdeviceAddr;
	for(loop = 0; loop < 4; loop++)
	{
		IDdevice[loop] = read_flash(addr);
		addr = addr + 4;
	}
}
/**********************************************************************
 * Read out data at Address()
 *
 * return data;
 **********************************************************************/
unsigned int read_flash(u32 Address) {
	/* Check the correction of written data */
	unsigned int Data;
	Data = (*(vu32*) Address);
	return Data;
}

/**********************************************************************
 * erase user flash zone
 *
 * return 1 if successful
 * 		  0 if not
 **********************************************************************/
int erase_flash() {
	u32 EraseCounter = 0x00;
	FLASHStatus = FLASH_COMPLETE;
	MemoryProgramStatus = PASSED;

	/* Define the number of page to be erased */
	//NbrOfPage = (EndAddr - StartAddr) / FLASH_PAGE_SIZE;

	/* Clear All pending flags */
	FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR
			| FLASH_FLAG_WRPRTERR);

	/* Unlock the Flash Program Erase controller */
	FLASH_Unlock();
	/* Erase the FLASH pages */
	for (EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus
			== FLASH_COMPLETE); EraseCounter++) {
		FLASHStatus = FLASH_ErasePage(StartAddr + (FLASH_PAGE_SIZE
				* EraseCounter));
	}
	FLASH_Lock();
	if (FLASHStatus == FLASH_COMPLETE) {
		return 1;
	} else {
		return 0;
	}
}

